package org.harsh.transmission.common.codec;

import cn.hutool.core.codec.Base64;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.lang.UUID;
import com.ruoyi.SpringUtil;
import com.ruoyi.common.core.domain.entity.SysDept;
import com.ruoyi.system.service.ISysDeptService;
import com.ruoyi.system.service.impl.SysDeptServiceImpl;
import io.netty.buffer.ByteBuf;
import io.netty.channel.Channel;
import io.netty.channel.ChannelHandler;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.MessageToByteEncoder;
import io.netty.handler.codec.MessageToMessageCodec;
import lombok.extern.slf4j.Slf4j;
import org.harsh.common.Config;
import org.harsh.common.Constants;
import org.harsh.dispatch.CommVars;
import org.harsh.transmission.common.CustomMsg;
import org.harsh.transmission.domain.TransMsg;
import org.harsh.transmission.domain.TransReceiver;
import org.harsh.transmission.domain.TransRecvmsg;
import org.harsh.transmission.domain.TransTask;
import org.harsh.transmission.server.NodeServer;
import org.harsh.transmission.service.ITransMsgService;
import org.harsh.transmission.service.ITransReceiverService;
import org.harsh.transmission.service.ITransRecvmsgService;
import org.harsh.transmission.service.ITransTaskService;
import org.harsh.transmission.service.impl.TransMsgServiceImpl;
import org.harsh.transmission.service.impl.TransRecvmsgServiceImpl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.net.InetSocketAddress;
import java.net.SocketAddress;
import java.util.List;

@Slf4j
@Component
@ChannelHandler.Sharable
public class PlainMsgCodec extends MessageToMessageCodec<CustomMsg, String> {
    @Autowired
    private ITransMsgService transMsgService;
    @Autowired
    private ITransTaskService transTaskService;
    @Autowired
    private ITransRecvmsgService transRecvmsgService;
    @Autowired
    private ITransReceiverService transReceiverService;

    /**
     * 解码
     *
     * @param ctx
     * @param customMsg
     * @param list
     * @throws Exception
     */
    @Override
    protected void decode(ChannelHandlerContext ctx, CustomMsg customMsg, List<Object> list) throws Exception {
        if (customMsg.getMsgType() == Constants.MessageType.TRANSMSG.getCode()) {
            byte transType = customMsg.getTransType();
            long msgId = customMsg.getMsgId();
            byte[] data = customMsg.getMsgData();
            String recvStr = new String(data, Config.DEFAULT_CHARSET);

            TransMsg transMsg = new TransMsg();
            transMsg.setMsgType(0l);
            transMsg.setTransType(0l);
            transMsg.setMsgId(msgId);
            transMsg.setMsgSize((long) data.length);
            transMsg.setFromNode((long) customMsg.getFromNode());
            transMsg.setFromType((long) customMsg.getFromType());
            transMsg.setFromId((long) customMsg.getFromId());
            transMsg.setMsgMd5(Base64.encode(customMsg.getMsgMd5()));
            transMsg.setMsgData(recvStr);
            transMsgService.insertTransMsg(transMsg);

            TransRecvmsg transRecvmsg = new TransRecvmsg();
            transRecvmsg.setMsgId(msgId);
            transRecvmsg.setTransType((long) transType);
            transRecvmsg.setRecvStatus(3l);
            transRecvmsg.setStartTime(DateUtil.date());
            transRecvmsg.setOverTime(DateUtil.date());
            transRecvmsgService.insertTransRecvmsg(transRecvmsg);

            TransReceiver transReceiver = new TransReceiver();
            transReceiver.setMsgId(msgId);
            if(customMsg.getRecvId() == 0) {
                // 接收对象为节点，1、业务系统发起；2、组播、广播；
                transReceiver.setRecvType(0l);
                transReceiver.setRecvNode(NodeServer.localDept.getDeptId());
                transReceiver.setRecvId(0l);
            } else {
                // 接收对象为节点用户，1、用户发起且选择了节点对应接收用户
                transReceiver.setRecvType(1l);
                transReceiver.setRecvNode(NodeServer.localDept.getDeptId());
                transReceiver.setRecvId((long) customMsg.getRecvId());
            }
            transReceiverService.insertTransReceiver(transReceiver);
            switch (transType) {
                case 0:
                    CustomMsg customer = new CustomMsg((byte) Constants.MessageType.ACKTRANSMSG.getCode(),
                            msgId, "OK".getBytes(Config.DEFAULT_CHARSET));
                    log.info("Received msg {} from peer : {}", msgId, recvStr);
                    ctx.writeAndFlush(customer);
                    break;
                case 1:
                    log.info("【组播】Received msg {}:{} from peer:{}", msgId, recvStr, customMsg.getFromNode());
                    break;
                case 2:
                    log.info("【广播】Received msg {}:{} from peer:{}", msgId, recvStr, customMsg.getFromNode());
                    break;
                case 3:
                    log.info("【单向】Received msg {}:{} from peer:{}", msgId, recvStr, customMsg.getFromNode());
            }
        } else if (customMsg.getMsgType() == Constants.MessageType.ACKTRANSMSG.getCode()) {
            long msgId = customMsg.getMsgId();
            InetSocketAddress address = (InetSocketAddress)ctx.channel().remoteAddress();
            String peerAddr = address.getAddress().getHostAddress();
            Long nodeId = CommVars.addr2Node.get(peerAddr);
            transTaskService.setTransSuccess(msgId, nodeId);

            log.info("Received ackmsg from peer , msgId : {}", msgId);
        }

    }


    /**
     * 编码
     *
     * @param ctx
     * @param s
     * @param list
     * @throws Exception
     */
    @Override
    protected void encode(ChannelHandlerContext ctx, String s, List<Object> list) throws Exception {
        long msgId = (long) Math.abs(UUID.randomUUID().hashCode());
        CustomMsg msg = new CustomMsg((byte) Constants.MessageType.TRANSMSG.getCode(), msgId, s.getBytes(Config.DEFAULT_CHARSET));
        log.info("Send Str to peer : {}", s);
        list.add(msg);
    }
}
